package main

// 定义1
// func sum(a int, b int) int {
// 	return a + b
// }

// 定义2 形参列表类型一样 可以省略前面的类型
// func sum(a, b int) int {
// 	return a + b
// }

// 定义3 函数的可变参数 可变参数是一个int类型的切片 可变参数一定要放在最后
// func sum(a ...int) int {
// 	sum := 0
// 	for _, v := range a {
// 		sum += v
// 	}
// 	return sum
// }

// 函数没有返回值 返回值列表啥都不用写

// 定义4 一次返回多个值
// func sum(x, y int) (int, int) {
// 	return x + y, x - y
// }

// 定义5 返回值具名
// func sum(x, y int) (sub int, sum int) {
// 	sub = x - y
// 	sum = x + y
// 	return
// }

// 定义6 返回具名 参数列表相同的也可以简写
// func sum(x, y int) (sub, sum int) {
// 	sub = x - y
// 	sum = x + y
// 	return
// }

// 定义7 返回具名 参数如果return不为return而是具体的值直接就覆盖已经操作的sub sum
// func sum(x, y int) (sub, sum int) {
// 	sub = x - y
// 	sum = x + y
// 	return 1, 2 // 直接覆盖了sub sum的值
// }

// 函数的作用域 局部作用域 函数或者结构语句内部 局部不常驻内存
// 全局在函数外部的 a := 这种声明方式不能放外边 全局变量只能用 var 全局常驻内存

// 函数类型和变量
// type Sa func(x int) int // 定义一个函数类型约束变量必须是这个类型

// 自定义类型
// type myInt int

func main() {
	// 函数也是引用类型
	// 定义
	// func 函数名字(形参列表)(返回值列表具名或者不具名直接写类型){}
	// 匿名函数可以定义在函数内 具名函数不可以定义在函数内
	// 访问作用域无法访问的变量undefined

	// sum, sub := sum(1, 2) // 返回多个返回值必须接收 不想接收就_
	// fmt.Println(sum, sub)

	// ！！！！！内部只能定义匿名函数，具名函数定义全局去 函数类型 默认值是nil a 存储的是函数的地址！！！！！ Type main.Sa
	// var a Sa = func(int) int {
	// 	return 0
	// }
	// fmt.Printf("%T", a)

	// var a myInt // 默认值0 %T main.myInt
	// fmt.Printf("%T", a)

	// var a = func() {  // %T func()

	// }
	// fmt.Printf("%T", a)

	// myInt 和 int不是一种类型 这两种声明也需要转换才能相加等等

	// 函数作为另一个函数的参数返回值 定义函数类型就行了这里就不演示了 (a Sa)Sa 按照约定传入对应的匿名函数或者具名函数就可以。

	// 行参或返回值可以直接用匿名函数类型约束

	// a := func(x func()) func() {
	// 	return func() {
	// 		fmt.Println("test")
	// 	}
	// }
	// x := a(func() {

	// })
	// x()

	// 自定义函数返回值 如果返回的是引用类型默认返回nil 值类型根据返回对应值类型的默认值就可以

	// 匿名函数没名字 可以定义全局或者函数内部，具名函数只能定义在全局

	// 匿名自执行函数
	// func ()  {

	// }()

	//递归调用自己调用自己的函数名字，注意死递归什么时候退出这个没啥讲的

	// 闭包 概念同js 就不详述了
	// var a = func() func() int {
	// 	a := 1
	// 	return func() int {
	// 		a++
	// 		return a
	// 	}
	// }

	// c := a()
	// c()
	// c()
	// c()
	// fmt.Println(c())

}
